﻿using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using NodeCanvas;
namespace NodeCanvas{
public class NGUIReferencesEditor : NodeEditor {
	int _sortMode = 1;
	Vector2 _atlasScrollView;
	Vector2 _spriteScrollView;
	NGUIAtlasDatas _datas;
	GameObject[] prefabs;
	protected override float _miniNodeAreHight {
		get {
			return 0;
		}
	}
	protected override string _currentCanvasName {
		get {
			return "";
		}
	}
	protected override bool _canDragNode {
		get {
			return false;
		}
	}

	[MenuItem("Assets/Node/NGUIReferences/Open Editor")]
	public static void Init(){
		var window =  GetWindow<NGUIReferencesEditor> ();
		window.StartFind ();
	}

	protected override void DrawMainTool ()
	{
		GUIStyle style = NodeStyles.breadcrumbLeft;
		GUIContent content = new GUIContent ("搜索");
		if (GUILayout.Button (content, style, GUILayout.Width (50))) {
				StartFind ();
		}
		style = NodeStyles.breadcrumbMiddle;
		content = new GUIContent ("正序");
		if (GUILayout.Button (content, style, GUILayout.Width (50))) {
			_sortMode = 1;
			Sort ();
		}

		content = new GUIContent ("反序");
		if (GUILayout.Button (content, style, GUILayout.Width (50))) {
			_sortMode = -1;
			Sort ();
		}
	}
	protected override void DrawLeftPanel ()
	{
		_atlasScrollView = EditorGUILayout.BeginScrollView (_atlasScrollView);
		if (_datas != null) {
			foreach(var v in _datas.datas){
				if (GUILayout.Button (v.Key.name))
					SelectAtlas (v.Value);
			}
		}
		EditorGUILayout.EndScrollView ();
	}
	protected override void DoNode (Node node)
	{
		base.DoNode (node);
		if (node is NGUINode) {
			NGUINode nguinode = ((NGUINode)node);
			node.infos [0].text = "Use:" + nguinode.sprite.useCount;
			Rect pos = node.position;
			float scale = 30;
			pos.position += _canvasOffset;
			pos.width = scale;
			pos.height = scale;
			GUI.DrawTextureWithTexCoords(pos,nguinode.sprite.texture,nguinode.sprite.uv);
		}

	}
	protected override void DrawRightPanel ()
	{
		if (_selectType == SelectType.Node) {
			if (_selectNode is NGUINode) {
				NGUINode nguinode = ((NGUINode)_selectNode);
				_spriteScrollView = EditorGUILayout.BeginScrollView (_spriteScrollView,GUILayout.MaxHeight(100));
					EditorGUILayout.BeginVertical ("box");
				for(int i = 0;i < nguinode.sprite.usePrefab.Count;i++){
					if (nguinode.sprite.usePrefab [i] == null)
						continue;
					int model = -1;
					if (AssetDatabase.IsMainAsset (nguinode.sprite.usePrefab [i]))
						model = 0;
					else if (nguinode.sprite.usePrefab [i].GetComponent<UISprite> () != null)
						model = 1;
					if (model == 0) {
						EditorGUI.indentLevel = model;	
						GUILayout.BeginHorizontal ();
						EditorGUILayout.ObjectField (nguinode.sprite.usePrefab [i], typeof(GameObject),true);
							if (model == 0 && GUILayout.Button ("Show"))
							GameObject.Instantiate (nguinode.sprite.usePrefab [i]);
						EditorGUILayout.EndHorizontal ();
					}
					EditorGUI.indentLevel = 0;
				}
				EditorGUILayout.Space ();
				EditorGUILayout.EndScrollView ();

				UISpriteData r = nguinode.sprite.atlas.GetSprite (nguinode.sprite.spriteName);
				float a = ((float)r.height) / r.width;
				Rect rect = new Rect (0,100,_rightPanelWidth , _rightPanelWidth*a);
				NGUIEditorTools.DrawTiledTexture(rect, NGUIEditorTools.backdropTexture);
				GUI.DrawTextureWithTexCoords(rect,nguinode.sprite.texture,nguinode.sprite.uv);
			}
		}
	}

	void SelectAtlas(AssetsAtlas datas){
		_nodes.Clear ();

		int index = 0;
		foreach(var v in datas.sprites){
			NGUINode node = new NGUINode ();
			node.type = NodeType.Node;
			node.name = v.Value.spriteName;
			node.sprite = v.Value;

			_nodes.Add (node);
			index++;
		}
		Sort ();
		UpdateNodePos ();
	}
	void StartFind(){
		_datas = new NGUIAtlasDatas ();
		if (_datas.error)
			_datas = null;
	}
	/// <summary>
	/// 排序列表
	/// </summary>
	void Sort(){
		List<NGUINode> nguinodes = new List<NGUINode> ();
		for (int i = 0; i < _nodes.Count; i++) {
			nguinodes.Add ((NGUINode)_nodes [i]);
		}

		if (_sortMode == 1)
			nguinodes.Sort (new SortNGUISpriteSequence ());
		else
			nguinodes.Sort (new SortNGUISpriteAntitone ());
		_nodes.Clear ();
		for (int i = 0; i < nguinodes.Count; i++) {
			_nodes.Add (nguinodes [i]);
		}
		UpdateNodePos ();
	}
	void UpdateNodePos (){
		int h = 200;
		int w = 50;
		int row = _maxCanvasScale / w;
		for (int i = 0; i < _nodes.Count; i++) {
			_nodes[i].position.position = new Vector2 (i / row * h, i % row * w);
		}
	}
}
/// <summary>
/// 展示的Node
/// </summary>
public class  NGUINode:Node{
	public AssetsSprite sprite;
}

public class NGUIAtlasDatas{
	public Dictionary<UIAtlas,AssetsAtlas> datas;
	public bool error;
	public NGUIAtlasDatas(){
		GameObject[] prefabs = AssetsFind.FindAllPrefab ();	
		if (prefabs == null) {
			error = true;
			return;
		}
		UIAtlas[] atlas;
		atlas = AssetsFind.Find<UIAtlas> (prefabs);
		datas = new Dictionary<UIAtlas,AssetsAtlas> ();
		for (int i = 0; i < atlas.Length; i++) {
			datas.Add(atlas [i], new AssetsAtlas (atlas [i]));
			EditorUtility.DisplayProgressBar ("Find Atlas", i.ToString (), (float)i / atlas.Length);
		}
		///搜索使用的
		UISprite[] sprites;
		sprites = AssetsFind.Find<UISprite> (prefabs);
		for (int i = 0; i < sprites.Length; i++) {
			if (sprites [i].atlas != null) {
				datas [sprites [i].atlas].AddUse (sprites [i].spriteName);
			}
			EditorUtility.DisplayProgressBar ("Find UISprite", i.ToString (), (float)i / sprites.Length);
		}
		for (int i = 0; i < prefabs.Length; i++) {
			if (prefabs [i] != null) {
				UISprite[] useSprite = prefabs [i].GetComponentsInChildren<UISprite> (true);
				for (int x = 0; x < useSprite.Length; x++) {
					AddReference (useSprite [x], prefabs [i]);
				}
			}
			EditorUtility.DisplayProgressBar ("Find Prefabs Used", i.ToString (), (float)i / prefabs.Length);
		}
		EditorUtility.ClearProgressBar ();
	}
	public void AddReference(UISprite sprite,GameObject prefab){
		if(sprite.atlas == null || !datas.ContainsKey(sprite.atlas)||!datas [sprite.atlas].sprites.ContainsKey(sprite.spriteName))
			return;
		if(!datas [sprite.atlas].sprites [sprite.spriteName].usePrefab.Contains(prefab))
			datas [sprite.atlas].sprites [sprite.spriteName].usePrefab.Add (prefab);
	}	
}
public class AssetsAtlas{
	public UIAtlas atlas;
	public Dictionary<string,AssetsSprite> sprites;
	public void AddUse(string name){
		if (sprites != null && sprites.ContainsKey (name))
			sprites [name].useCount++;
	}
	public AssetsAtlas(UIAtlas data){
		atlas = data;
		sprites = new Dictionary<string,AssetsSprite>();
		for (int i = 0; i < data.spriteList.Count; i++) {
			AssetsSprite sp = new AssetsSprite ();
			sp.atlas = data;
			sp.spriteName = atlas.spriteList [i].name;
			sprites.Add (sp.spriteName,sp);
		}
	}
	public void ClearPrefab(){
		foreach (var v in sprites) {
			v.Value.usePrefab.Clear ();
		}
	}
}
public class AssetsSprite{
	public UIAtlas atlas;
	public string spriteName = "";
	public int useCount;
	public List<GameObject> usePrefab = new List<GameObject>();
	public Rect uv{
		get{ 
			UISpriteData sprite = atlas.GetSprite(spriteName);
			Rect uv = new Rect(sprite.x, sprite.y, sprite.width, sprite.height);
			uv = NGUIMath.ConvertToTexCoords(uv, texture.width, texture.height);
			return uv;
		}
	}
	public Texture texture{
		get{ 
			return  atlas.texture as Texture2D;
		}
	}
}
public class SortNGUISpriteSequence:IComparer<NGUINode>{
	public int Compare(NGUINode x,NGUINode y){
		if (x == null && y == null) return 0;
		if (x == null) return -1;
		if (y == null) return 1;
		{
			if (x.sprite.useCount > y.sprite.useCount)
				return -1;
			if (x.sprite.useCount < y.sprite.useCount)
				return 1;
		}
		return 0;
	}
}
public class SortNGUISpriteAntitone:IComparer<NGUINode>{
	public int Compare(NGUINode x,NGUINode y){
		if (x == null && y == null) return 0;
		if (x == null) return -1;
		if (y == null) return 1;
		{
			if (x.sprite.useCount > y.sprite.useCount)
				return 1;
			if (x.sprite.useCount < y.sprite.useCount)
				return -1;
		}
		return 0;
	}
}
}